import json


from django.shortcuts import render
from django.http import JsonResponse
from django.forms.models import model_to_dict
from django.db.models import F
from django.views.decorators.csrf import csrf_exempt


from app01.utils.form.file_form import FileFolderModelForm, FileModelForm
from app01 import models
from app01.utils.cos import delete_file, delete_file_list, get_credentials

def file(request, project_id):
    """ 文件列表 & 添加文件夹 """
    # 获取当前目录对象
    parent_object = None
    folder_id = request.GET.get('folder_id',"")
    if folder_id.isdecimal():
        folder_id = int(folder_id)
        parent_object = models.FileRepository.objects.filter(file_type=2, id=folder_id, project=request.tracer.project).first()

    if request.method == "GET":
        breadcrumb_list = []
        parent = parent_object
        while parent:
            # breadcrumb_list.insert(0, {"id": parent.id, "name": parent.name})
            breadcrumb_list.insert(0, model_to_dict(parent, ['id', 'name']))
            parent = parent.parent

        # 获取当前目录下的所有文件 & 文件夹
        queryset = models.FileRepository.objects.filter(project=request.tracer.project)
        if parent_object:
            # 进入了某个目录
            file_object_list = queryset.filter(parent=parent_object).order_by('-file_type')
        else:
            file_object_list = queryset.filter(parent__isnull=True).order_by('-file_type')

        form = FileFolderModelForm(request, parent_object)

        context = {
            "form": form, 
            "breadcrumb_list": breadcrumb_list, 
            "file_object_list": file_object_list,
            "folder_object": parent_object
            }
        return render(request, "file.html", context)
    
    # 添加文件夹 & 文件夹的修改

    fid = request.POST.get('fid')

    # 编辑对象能否找到
    edit_object = None
    if  fid.isdecimal():
        edit_object = models.FileRepository.objects.filter(file_type=2, id=int(fid), project=request.tracer.project).first()

    if edit_object:
        # 找到, 修改文件夹
        form = FileFolderModelForm(request, parent_object, request.POST, instance=edit_object)
    else:
        # 找不到, 添加文件夹
        form = FileFolderModelForm(request, parent_object, request.POST)

    if form.is_valid():
        form.instance.project = request.tracer.project
        form.instance.file_type = 2
        form.instance.update_user = request.tracer.user
        form.instance.parent = parent_object
        form.save()
        return JsonResponse({"status": True})  
     
    return JsonResponse({"status": False, "error": form.errors})


def file_delete(request, project_id):
    """ 删除文件 """
    # 删除数据库中的文件与文件夹 - 级联删除
    delete_object = models.FileRepository.objects.filter(id=request.GET.get('fid'), project=request.tracer.project).first()

    """ 删除文件 (数据库、cos文件、项目空间归还) """
    if delete_object.file_type == 1:
        # 1 - 归还空间 (原子操作)
        request.tracer.project.use_space = F('use_space') - delete_object.file_size
        request.tracer.project.save()

        # 2 - cos 删除文件
        delete_file(request.tracer.project.bucket, request.tracer.project.region, delete_object.key)

        # 3 - 删除数据库中的文件
        delete_object.delete()

        return JsonResponse({"status": True})

    """ 删除文件夹（找到文件夹下所有的文件 - 数据库、cos文件、项目空间归还） """
    total_size = 0
    key_list = []

    folder_list = [delete_object, ]
    for folder in folder_list:
        child_list = models.FileRepository.objects.filter(parent=folder, project=request.tracer.project).order_by('-file_type')
        for child in child_list:
            if child.file_type == 2:
                folder_list.append(child)  
            else:
                # 文件大小汇总
                total_size += child.file_size

                # 删除文件
                key_list.append({"Key": child.key})
            

    # cos 批量删除文件
    if key_list:
        delete_file_list(request.tracer.project.bucket, request.tracer.project.region, key_list)

    # 归还空间
    if total_size:
        request.tracer.project.use_space = F('use_space') - total_size
        request.tracer.project.save()

    # 删除数据库中的文件
    delete_object.delete()

    return JsonResponse({"status": True})

@csrf_exempt
def cos_credentials(request, project_id):
    """ cos上传临时凭证获取 """

    # 文件限制 M - 转化为字节
    per_file_limit = request.tracer.price_policy.per_file_size * 1024 * 1024
    total_file_limit = request.tracer.price_policy.project_space * 1024 * 1024 *1024

    # 总容量
    total_size = 0

    # 获取上传的每个文件 & 文件大小
    file_list = json.loads(request.body.decode('utf-8'))
    for item in file_list:
        # 文件的字节大小item['size']
        if item['size'] > per_file_limit:
            msg = "单文件: {} 过大, 最大限制{}M, 如需更多请升级或购买".format(item['name'], request.tracer.price_policy.per_file_size)
            return JsonResponse({"status": False, "error": msg})
        total_size += item['size']

    # 总容量限制
    if request.tracer.project.use_space  + total_size >  total_file_limit:
        msg = "总容量已满, 如需更多请升级或购买"
        return JsonResponse({"status": False, "error": msg})


    # 容量限制: 单文件 & 总容量

    result_dict = get_credentials(request.tracer.project.bucket, request.tracer.project.region)
    
    return JsonResponse({"status": True, "data": result_dict})

@csrf_exempt
def file_post(request, project_id):
    """ 上传文件成功写入数据库 """
    """ 
    name: fileName,
    key: key,
    file_size: fileSize,
    parent: CURRENT_FOLDER_ID,
    etag: data.ETag,
    file_path: data.Location
    """

    # 根据key去cos获取文件Etag效验访问合法不
    form = FileModelForm(request, data=request.POST)
    
    if form.is_valid():
        data_dict = form.cleaned_data
        data_dict.pop('etag')
        data_dict.update({'project': request.tracer.project, 'file_type': 1, 'update_user': request.tracer.user})
        instance = models.FileRepository.objects.create(**data_dict)
        
        # 项目的已使用空间：更新 (data_dict['file_size'])
        request.tracer.project.use_space += data_dict['file_size']
        request.tracer.project.save()

        result = {
             'id': instance.id,
             'name': instance.name,
             'file_size': instance.file_size,
             'username': instance.update_user.usermail,
             'datetime': instance.update_datetime.strftime("%Y年%m月%d日 %H:%M"),
             # 'file_type': instance.get_file_type_display()
         }
        return JsonResponse({"status": True, "data": result})


    return JsonResponse({"status": False, "error": form.errors})